package com.dingwen.treasure.websocket.server.handler;

import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.web.socket.*;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 　TreasureWebsocketHandler
 * 　@author dingwen
 * 　@date 2022/8/31
 */
@Component("treasureWebsocketHandler")
@Slf4j
public class TreasureWebsocketHandler implements WebSocketHandler {


    /**
     * SESSION
     */
    private final static Map<String, WebSocketSession> SESSION = new ConcurrentHashMap<>();

    /**
     * 连接建立之后触发端回调
     *
     * @param webSocketSession web socket会话
     */
    @Override
    public void afterConnectionEstablished(WebSocketSession webSocketSession) {
        //TODO 后期考虑属性传参或查询、路径、sessionId等、
        String channel = "666666";
        if (!SESSION.containsKey(channel)) {
            SESSION.put(channel, webSocketSession);
        }
        log.info("channel:{}", channel);
        log.info("连接建立之后触发端回调");
    }

    /**
     * 收到消息时触发的回调
     *
     * @param webSocketSession web socket会话
     * @param webSocketMessage 网络套接字信息
     */
    @Override
    public void handleMessage(WebSocketSession webSocketSession, WebSocketMessage<?> webSocketMessage) {
        log.info("webSocketMessage:{}", webSocketMessage);
        log.info("收到消息时触发的回调");
    }

    /**
     * 传输消息出错时触发调回调
     *
     * @param webSocketSession web socket会话
     * @param throwable        throwable
     */
    @Override
    public void handleTransportError(WebSocketSession webSocketSession, Throwable throwable) {
        log.info("传输消息出错时触发调回调");
    }

    /**
     * 断开连接后触发的回调
     *
     * @param webSocketSession web socket会话
     * @param closeStatus      关闭状态
     */
    @Override
    public void afterConnectionClosed(WebSocketSession webSocketSession, CloseStatus closeStatus) {
        log.info("断开连接后触发的回调");
    }

    /**
     * 是否处理分片消息
     *
     * @return boolean
     */
    @Override
    public boolean supportsPartialMessages() {
        return false;
    }


    /**
     * 发送消息
     *
     * @param channel 通道
     * @param message 消息
     */
    @SneakyThrows(Throwable.class)
    public void sendMessage(String channel, String message) {
        if (isConnected(channel)) {
            WebSocketSession webSocketSession = SESSION.get(channel);
            webSocketSession.sendMessage(new TextMessage(message));
            log.info("服务端消息已发送：{}", message);
        }
    }

    /**
     * 判断连接是否在线
     *
     * @param channel 通道
     * @return boolean
     */
    public static boolean isConnected(String channel) {
        if (!SESSION.containsKey(channel)) {
            return false;
        }
        WebSocketSession webSocketSession = SESSION.get(channel);
        return !(ObjectUtils.isEmpty(webSocketSession) || !webSocketSession.isOpen());
    }
}
